package com.lu.sb210207.service.impl;

import com.lu.sb210207.entity.ScheduleTrigger;
import com.lu.sb210207.entity.ScheduleTriggerParam;
import com.lu.sb210207.exception.ScheduleException;
import com.lu.sb210207.mapper.ScheduleTriggerParamMapper;
import com.lu.sb210207.service.SchedulerService;
import lombok.extern.slf4j.Slf4j;
import org.quartz.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;

/**
 * 对Quartz定时任务进行增、删、改、查、暂停、开始。使用scheduler对定时任务进行操作。
 */
// 更详细增删之类的操作：https://blog.csdn.net/weixin_33937499/article/details/92183790
@Service
@Slf4j
public class ScheduledServiceImpl implements SchedulerService {

    @Resource
    private Scheduler scheduler;

    @Autowired
    private ScheduleTriggerParamMapper scheduleTriggerParamMapper;

    /**
     * 增加定时任务
     * @param scheduleTrigger
     */
    @Override
    public void addJob(ScheduleTrigger scheduleTrigger) {


        try {
            // 启动调度器
//            scheduler.start();

            //根据Jobname和JobGroup生成TriggerKey
            TriggerKey triggerKey = TriggerKey.triggerKey(scheduleTrigger.getJobName(), scheduleTrigger.getJobGroup());

            //根据TriggerKey获取Scheduler调度器中的触发器，并判断是否为null，不为null即存在
            CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);

            // Quartz调度器实例已经存在
            if (trigger != null) {
//                // 0代表不执行的任务
//                if (scheduleTrigger.getStatus().equals("0")) {
//                    JobKey jobKey = JobKey.jobKey(scheduleTrigger.getJobName(), scheduleTrigger.getJobGroup());
//                    // 停止触发器
//                    scheduler.pauseTrigger(triggerKey);
//                    // 移除触发器
//                    scheduler.unscheduleJob(triggerKey);
//                    // 删除定时任务
//                    scheduler.deleteJob(jobKey);
//                    // 或者此处抛出异常（return）
//                    throw new ScheduleException("该定时任务禁止执行！");
//                }
//                //获取调度器中的表达式
//                String cronExpression = trigger.getCronExpression();
//                //将调度器中的cron与数据库中的job任务进行比对
//                if (!scheduleTrigger.getCron().equals(cronExpression)) {
//                    //重构表达式调度器
//                    CronScheduleBuilder newCronSchedule = CronScheduleBuilder.cronSchedule(scheduleTrigger.getCron());
//                    //重构CronTrigger
//                    trigger = TriggerBuilder.newTrigger()
//                            .withIdentity(triggerKey)
//                            .withSchedule(newCronSchedule)
//                            .build();
//                    //刷新调度器实例
//                    scheduler.rescheduleJob(triggerKey, trigger);
//                }
                // 或者此处抛出异常（return）
                throw new ScheduleException("该定时任务已存在！");
            }

            // Quartz调度器实例不存在
            if (scheduleTrigger.getStatus().equals("0")){

                throw new ScheduleException("该定时任务禁止执行！");
            }
            // 构建job信息
            JobDetail jobDetail = JobBuilder.newJob((Class<? extends Job>) Class.forName(scheduleTrigger.getJobName()))
                    .withIdentity(scheduleTrigger.getJobName(), scheduleTrigger.getJobGroup())
                    .build();

            //传递参数到job任中
            JobDataMap jobDataMap = jobDetail.getJobDataMap();
            //获取调度器任务id得到数据库中的参数列表
            Integer scheduleid = scheduleTrigger.getId();
            List<ScheduleTriggerParam> params = scheduleTriggerParamMapper.queryScheduleParams(scheduleid);
            for (ScheduleTriggerParam param : params) {
                jobDataMap.put(param.getName(), param.getValue());
            }

            // 创建cron表达式调度器
            CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(scheduleTrigger.getCron());
            // 创建cron表达式触发器
            trigger = TriggerBuilder.newTrigger()
                    .withIdentity(scheduleTrigger.getJobName(), scheduleTrigger.getJobGroup())
                    .withSchedule(cronScheduleBuilder)
                    .build();
            // 将jobDetail和Trigger注入到调度器中
            scheduler.scheduleJob(jobDetail, trigger);

        } catch (SchedulerException | ClassNotFoundException e) {
            log.error("创建定时任务失败" + e);
        }
    }

    /**
     * 暂停定时任务
     * @param jobName
     * @param jobGroup
     */
    @Override
    public void jobPause(String jobName, String jobGroup) {

        try {
            // 判断是否存在该定时任务
            TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroup);

            CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);

            if (trigger == null) {

                throw new ScheduleException("该定时任务不存在！");
            }
            scheduler.pauseJob(JobKey.jobKey(jobName, jobGroup));
        } catch (SchedulerException e) {
            log.error("暂停定时任务失败::" + e);
        }
    }

    /**
     * 开始定时任务
     * @param jobName
     * @param jobGroup
     */
    @Override
    public void jobResume(String jobName, String jobGroup) {

        try {
            // 判断是否存在该定时任务
            TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroup);

            CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);

            if (trigger == null) {

                throw new ScheduleException("该定时任务不存在！");
            }
            scheduler.resumeJob(JobKey.jobKey(jobName, jobGroup));
        } catch (SchedulerException e) {
            log.error("开启定时任务失败::" + e);
        }
    }

    /**
     * 删除定时任务
     * @param jobName
     * @param jobGroup
     */
    @Override
    public void jobdelete(String jobName, String jobGroup) {

        try {
            // 判断是否存在该定时任务
            TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroup);

            CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);

            if (trigger == null) {

                throw new ScheduleException("该定时任务不存在！");
            }
            // 停止触发器
            scheduler.pauseTrigger(TriggerKey.triggerKey(jobName, jobGroup));
            // 移除触发器
            scheduler.unscheduleJob(TriggerKey.triggerKey(jobName, jobGroup));
            // 删除任务
            scheduler.deleteJob(JobKey.jobKey(jobName, jobGroup));
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
    }

    /**
     * 更新定时任务
     * @param scheduleTrigger
     */
    @Override
    public void updateJob(ScheduleTrigger scheduleTrigger) {

        try {

            // 判断是否存在该定时任务
            TriggerKey triggerKey = TriggerKey.triggerKey(scheduleTrigger.getJobName(), scheduleTrigger.getJobGroup());

            CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);

            if (trigger == null) {

                throw new ScheduleException("该定时任务不存在！");
            }

            // 表达式调度构建器
            CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(scheduleTrigger.getCron());

            // 按新的cronExpression表达式重新构建trigger
            trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();

            // 按新的trigger重新设置job执行
            scheduler.rescheduleJob(triggerKey, trigger);

        } catch (SchedulerException e) {
            log.error("更新定时任务失败" + e);
        }
    }
}
